package cate.game.role.bag.favorability;

import cate.common.table.d.GDFavorability;
import cate.common.table.d.GDObj;
import cate.common.table.d.GDOperation;
import cate.common.table.item.favorability.row.FavorabilityAttrRow;
import cate.common.table.item.favorability.row.FavorabilityBaseRow;
import cate.common.table.item.favorability.row.FavorabilityStarRow;
import cate.common.table.item.hero.row.HeroBaseRow;
import cate.common.util.GameResult;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.play.support.PlayBuildContext;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.RoleDependent;
import cate.game.role.bag.hero.Hero;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.pattern.ICopiable;
import cp.solution.util.collection.ListKit;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import easy.java.practice.errorcode.EcResult;
import org.springframework.data.annotation.Transient;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@NoteClass("英雄身上的好感度数据")
public class FavorabilityOn extends RoleDependent implements ICopiable<FavorabilityOn> {
    @Transient
    @JsonIgnore
    public Hero owner;

    @NoteField("嗑药数量数据")
    public List<FavorabilityAttr> favorabilitysAttrs;

    public void initialize(Hero hero, Role role) {
        super.initialize(role);
        this.owner = hero;
        if (favorabilitysAttrs == null) {
            favorabilitysAttrs = new ArrayList<>();
        }
        initFavorabilitysAttrs();
    }

    private void initFavorabilitysAttrs() {
        if (role == null) {
            return;
        }
        List<FavorabilityAttrRow> rows = role.getGame().table.favorability.attr.getList();
        for (FavorabilityAttrRow row : rows) {
            if (findAttr(row.attr) == null) {
                FavorabilityAttr attr = new FavorabilityAttr(row.attr);
                favorabilitysAttrs.add(attr);
            }
        }
        favorabilitysAttrs.forEach(FavorabilityAttr::initialize);
    }

    /**
     * 提升好感度
     * @param favorabilityItems item
     */
    public GameResult<Void> improve(MixRes favorabilityItems){
        GameResult<Void> gameResult = new GameResult<>();
        if (favorabilityItems == null || favorabilityItems.items.size() != 1 || favorabilityItems.items.get(0).num <= 0) {
            return gameResult.fail("错误的道具");
        }
        if (owner == null) {
            return gameResult.fail("英雄不存在");
        }
        HeroBaseRow heroBaseRow = owner.getTpl(role.getGame().fight.getPlayBuildContext());
        if (heroBaseRow == null) {
            return gameResult.fail("英雄不存在");
        }
        if (heroBaseRow.strength < 2) {
            return gameResult.fail("SSR英雄才可提升好感度");
        }
        FavorabilityStarRow starRow = role.getGame().table.favorability.star.getRow(heroBaseRow.star);
        if (starRow == null) {
            return gameResult.fail("该英雄无法提升好感度");
        }
        MixResItem item = favorabilityItems.items.get(0);
        FavorabilityBaseRow row = role.getGame().table.favorability.base.get(item.tid);
        if (row == null) {
            return gameResult.fail("错误的好感度道具");
        }
        long maxUseTimes = starRow.prop1 + starRow.prop2 + starRow.prop3;
        int tmpUseTimes = favorabilitysAttrs.stream().mapToInt(e -> e.times.getOrDefault(item.tid,0)).sum();
        if (item.num > maxUseTimes - tmpUseTimes) {
            return gameResult.fail("超出使用数量限制啦");
        }
        if (row.attrId > 0) {
            FavorabilityAttrRow attrRow = role.getGame().table.favorability.attr.get(row.attrId);
            if (attrRow == null) {
                return gameResult.fail("错误的好感度属性");
            }
            FavorabilityAttr attr = favorabilitysAttrs.get(row.attrId);
            if (attr != null) {
                return gameResult.fail("超出使用数量限制啦");
            }
        }
        EcResult<MixResItem> consumeRes = favorabilityItems.consume(role, null);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return gameResult.fail(consumeRes);
        }
        if (GDFavorability.ItemType.isRandom(row.type)) {
            Map<Integer, Integer> attrLimits = new HashMap<>();
            attrLimits.put(findAttrId(GDFavorability.AttrMapping.PROP1.getAttrIndex()), starRow.prop1);
            attrLimits.put(findAttrId(GDFavorability.AttrMapping.PROP2.getAttrIndex()), starRow.prop2);
            attrLimits.put(findAttrId(GDFavorability.AttrMapping.PROP3.getAttrIndex()), starRow.prop3);
            for (int i=0; i<item.num; ++i) {
                Map<Integer, Integer> attrNums = favorabilitysAttrs.stream().collect(Collectors.toMap(e -> e.attrId, e -> e.times.getOrDefault(item.tid, 0)));
                FavorabilityAttrRow attrRow = role.getGame().table.favorability.attr.randomAttr(attrNums, attrLimits);
                if (attrRow == null) {
                    logger.error("怎么会没有随机的属性呢,name={}, heroid={}, attrs={}", role.getBase().name, owner.tid, favorabilitysAttrs);
                    continue;
                }
                FavorabilityAttr attr = findAttr(attrRow.attr);
                if (attr == null) {
                    //修正数据
                    attr = new FavorabilityAttr(attrRow.attr);
                    favorabilitysAttrs.add(attr);
                }
                attr.addValue(item.tid, 1, attrRow.addValue);
            }
        } else {
            FavorabilityAttrRow attrRow = role.getGame().table.favorability.attr.get(row.attrId);
            if (attrRow != null) {
                FavorabilityAttr attr = findAttr(attrRow.attr);
                if (attr == null) {
                    //修正数据
                    attr = new FavorabilityAttr(attrRow.attr);
                    favorabilitysAttrs.add(attr);
                }
                attr.addValue(item.tid, (int) item.num, attrRow.addValue * item.num);
            }
        }
        return gameResult;
    }

    @JsonIgnore
    private int findAttrId(int attrIndex) {
        return role.getGame().table.favorability.attr.getAttr(attrIndex).attr;
    }

    private FavorabilityAttr findAttr(int attrId) {
        return favorabilitysAttrs.stream().filter(e -> e.attrId == attrId).findAny().orElse(null);
    }


    /**
     * 重置药
     */
    public RewardShow resetFavorability(MergeMsgSender sender, boolean updatePower){
        RewardShow rewardShow = new RewardShow();
        if (owner == null || favorabilitysAttrs.isEmpty()) {
            return rewardShow;
        }
        MixRes reward = new MixRes();
        for (FavorabilityAttr attr : favorabilitysAttrs) {
            for (Map.Entry<Integer, Integer> entry : attr.times.entrySet()) {
                reward.addList(new MixRes(GDObj.getMixResStr(GDObj.Type.PROP, entry.getKey(), entry.getValue())));
            }
        }
        if (reward.isEmpty()) {
            return rewardShow;
        }
        favorabilitysAttrs.forEach(FavorabilityAttr::reset);
        reward.add(role, true, GDOperation.FAVORABILITY_RESET, sender);
        rewardShow.addTplRwd(reward);
        if (updatePower) {
            role.getBase().updatePower();
            publishEvent(role, new HeroPowerChangeEvent(role, owner));
        }
        return rewardShow;
    }

    @JsonIgnore
    public FavorabilityPowerAttrPart getPowerAttrPart(PlayBuildContext ctx) {
        return new FavorabilityPowerAttrPart(ctx,this);
    }

    @Override
    public FavorabilityOn copy() {
        FavorabilityOn cp = new FavorabilityOn();
        cp.favorabilitysAttrs = ListKit.cloneList(favorabilitysAttrs, FavorabilityAttr::copy);
        cp.initialize(owner, role);
        return cp;
    }
}
